﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using System.Web.Http;
using Newtonsoft.Json;
using Sustainalytics.ClientDW.DataAccessLayer;
using Sustainalytics.ClientDW.DataAccessLayer.ESGRatings;
using Sustainalytics.DataLayer;
using Sustainalytics.DataLayer.ConnectionStrings;
using Sustainalytics.DataLayer.Shared;
using Sustainalytics.Entities.ConnectionStrings;
using Sustainalytics.Entities.ESGRatings;
using Sustainalytics.ESGRatings.BusinessLogic;
using Sustainalytics.ESGRatings.Service.Models;
using Sustainalytics.Utils;
using Sustainalytics.Utils.WebApi.ErrorCodes;
using System.Web.Http.Cors;

namespace Sustainalytics.ESGRatings.Service.Controllers
{
    using Sustainalytics.DataLayer.EsgRatings;    

    [EnableCors(origins: "*", headers: "*", methods: "*")]
    // [ClaimsChecker("api/v1/company/esg")]
    //[ClaimsChecker("api/v1/esgratings/referenceUniverses")]
    [RoutePrefix("api/v1/esgratings/referenceUniverses")]
    [LogControllerFilter(true, true, false)]
    public class ReferenceUniversesController : ApiController
    {
        private IReferenceUniversesManagement _referenceUniversesManagement;
        //ESGEventSource log;

        public ReferenceUniversesController()
        {

        }

        public ReferenceUniversesController(IReferenceUniversesManagement referenceUniversesManagement)// unit testing constructor
        {
            _referenceUniversesManagement = referenceUniversesManagement;
        }

        [Route("{referenceUniverseName}")]
        [HttpGet]
        public HttpResponseMessage Get(string referenceUniverseName)
        {
            HttpResponseMessage responseMessage = null;
            SetControllerDependencies();
            try
            {
                byte[] excelData = _referenceUniversesManagement.GetESGFileByName(referenceUniverseName);

                responseMessage = new HttpResponseMessage(HttpStatusCode.OK);
                using (var stream = new MemoryStream(excelData))
                {
                    responseMessage.Content = new StreamContent(stream);
                    responseMessage.Content.Headers.ContentType =
                        new MediaTypeHeaderValue("application/vnd.ms-excel");
                    responseMessage.Content.Headers.ContentDisposition =
                        new ContentDispositionHeaderValue("attachment")
                        {
                            FileName = referenceUniverseName + ".xls"
                        };
                }

            }
            catch (Exception ex)
            {
                CommonEventSource.Log.Exception(ex);
                Request.CreateResponse(HttpStatusCode.InternalServerError);
            }

            return responseMessage;
        }


        [Route("")]
        [HttpGet]
        public List<ReferenceUniverseDto> Get()
        {
            //if (_referenceUniversesManagement == null)
            //{
            var clientConnectionString = ConfigurationManager.ConnectionStrings["ClientPlatform"].ConnectionString;
            var connectionStringsManager =
                    ConnectionStringsManager.GetInstance(ConnectionStringsRepository.GetInstance(clientConnectionString));
            var clientDwConnectionString = connectionStringsManager.GetConnectionString(ConnectionStringType.ClientDW);
            //    var dataCacheConnectionString = ConfigurationManager.AppSettings["RedisServer"];// strangely this connection string is stored in AppSettings

            //    var clientDwRepository = ClientDwRepository.GetInstance(clientDwConnectionString);
            //    var esgInputFileRepository = EsgInputFileRepository.GetInstance(new FileRepository(clientConnectionString),
            //        new RepositoryCollection<EsgInputFile>(clientConnectionString));
            //var referenceUniversesRepository = ReferenceUniversesRepository.GetInstance(clientDwConnectionString);

            //    var dataCache = ESGRatingsRedisCache.BasicESGRatingsAppCache(dataCacheConnectionString);

            //    _referenceUniversesManagement = ReferenceUniversesManagement.GetInstance(esgInputFileRepository, clientDwRepository, referenceUniversesRepository, dataCache);
            //}

            //var referenceUniverses = _referenceUniversesManagement.GetReferenceUniverses(false);
            // asa a zis petre
            var repoCollection = new RepositoryCollection<ReferenceUniverse>(clientDwConnectionString);
            var referenceUniverses = repoCollection.ReadWhere(a => true, null, null,
                Ordering<ReferenceUniverse>.Ascending(d => d.Name), a => a.Id, a => a.Name);
            var findDefault = referenceUniverses.FirstOrDefault(a => a.Name.ToLowerInvariant().Trim().Equals("default"));
            if (findDefault != null)
            {
                referenceUniverses.Remove(findDefault);
                referenceUniverses.Insert(0, findDefault);
            }
            return referenceUniverses == null ? Enumerable.Empty<ReferenceUniverseDto>().ToList() : referenceUniverses.Select(r => new ReferenceUniverseDto() { Id = r.Id, Name = r.Name }).ToList();
        }

        [Route("")]
        [HttpPost]
        public async Task<HttpResponseMessage> Post()
        {
            SetControllerDependencies();
            try
            {
                if (!Request.Content.IsMimeMultipartContent())
                {
                    Request.CreateResponse(HttpStatusCode.UnsupportedMediaType);
                }

                var provider = GetMultipartProvider();
                var result = await Request.Content.ReadAsMultipartAsync(provider);


                var originalFileName = GetDeserializedFileName(result.FileData.First());

                var fileUploadObj = GetFormData<FormData>(result);
                FormData form = (FormData)fileUploadObj;

                var uploadedFileInfo = new FileInfo(result.FileData.First().LocalFileName);
                string contentType = result.FileData.First().Headers.ContentType.ToString();
                byte[] dataFile = File.ReadAllBytes(uploadedFileInfo.FullName);
                var returnData = _referenceUniversesManagement.SaveReferenceUniverse(dataFile, originalFileName, form.UniverseName, contentType);
                File.Delete(uploadedFileInfo.FullName);

                if (string.IsNullOrEmpty(returnData))
                {
                    return Request.CreateResponse(HttpStatusCode.OK);
                }
                return Request.CreateResponse(HttpStatusCode.OK, new { returnData });


            }
            catch (Exception ex)
            {
                CommonEventSource.Log.Exception(ex);
                return Request.CreateResponse(HttpStatusCode.InternalServerError,
                                              new { ErrorStatusCode = WebAPIGeneralErrorCodes.UnhandledException });
            }
        }

        private void SetControllerDependencies()
        {
            if (_referenceUniversesManagement == null)
            {
                var clientConnectionString = ConfigurationManager.ConnectionStrings["ClientPlatform"].ConnectionString;
                var connectionStringsManager =
                    ConnectionStringsManager.GetInstance(ConnectionStringsRepository.GetInstance(clientConnectionString));
                var clientDwConnectionString = connectionStringsManager.GetConnectionString(ConnectionStringType.ClientDW);

                var clientDwRepository = ClientDwRepository.GetInstance(clientDwConnectionString);
                var esgInputFileRepository = EsgInputFileRepository.GetInstance(new FileRepository(clientConnectionString),
                    new RepositoryCollection<EsgInputFile>(clientConnectionString));
                var referenceUniversesRepository = ReferenceUniversesRepository.GetInstance(clientDwConnectionString);

                _referenceUniversesManagement = ReferenceUniversesManagement.GetInstance(esgInputFileRepository,
                    clientDwRepository, referenceUniversesRepository);
            }
        }

        private string GetDeserializedFileName(MultipartFileData fileData)
        {
            var fileName = fileData.Headers.ContentDisposition.FileName;
            return JsonConvert.DeserializeObject(fileName).ToString();
        }
        private MultipartFormDataStreamProvider GetMultipartProvider()
        {
            var uploadFolder = @"TempFileUploads";
            var root = uploadFolder;
            Directory.CreateDirectory(root);
            return new MultipartFormDataStreamProvider(root);
        }

        private object GetFormData<T>(MultipartFormDataStreamProvider result)
        {
            if (result.FormData.HasKeys())
            {
                var unescapedFormData = Uri.UnescapeDataString(stringToUnescape: result.FormData
                    .GetValues(0).FirstOrDefault() ?? String.Empty);
                if (!String.IsNullOrEmpty(unescapedFormData))
                    return JsonConvert.DeserializeObject<T>(unescapedFormData);
            }

            return null;
        }
    }
}
